import { HttpUtil } from '@/utils/HttpUtil';
import { ObjectUtil } from '@/utils/ObjectUtil';

export default {
	name: 'ManageTable',
	props: {
		service: {
			type: Object,
			required: true
		},
		/**
		 * @author 戴俊明 <idaijunming@163.com>
		 * @description ManageTable选项
		 * @date 2020/6/3 16:13
		 * label: string 搜索标签、表头
		 * value: string 字段名
		 * editable: boolean 此字段可编辑（默认true）
		 * type: string (value,category,time)
		 * options: Array category 用于离散的类目数据
		 * format: function 格式化字段的值
		 **/
		options: {
			type: Array,
			required: true
		},
		defaultRecord: {
			type: Object,
			required: true
		},
		insertAction: {
			type: Boolean,
			default: function() {
				return true;
			}
		},
		updateAction: {
			type: Boolean,
			default: function() {
				return true;
			}
		},
		deleteAction: {
			type: Boolean,
			default: function() {
				return true;
			}
		},
		batchDeleteAction: {
			type: Boolean,
			default: function() {
				return true;
			}
		},
		selectAction: {
			type: Boolean,
			default: function() {
				return true;
			}
		}
	},
	data() {
		return {
			searchControl: {
				choice: null,
				query: {}
			},
			tableControl: {
				loading: false,
				tableData: [],
				prop: null,
				order: null,
				selection: null
			},
			editControl: {
				editable: false,
				isPlus: false,
				temp: null
			},
			deleteControl: {
				deletable: false,
				isBatch: false,
				deleteRow: null,
				deleteRows: null
			},
			pageControl: {
				total: 0,
				current: 1,
				pageSize: 10,
				pages: 0
			}
		};
	},
	mounted() {
		this.select().catch(e => {
			this.$message.error(e.message);
		});
		this.searchControl.query = ObjectUtil.clone(this.defaultQuery);
	},
	computed: {
		tableOptions: function() {
			return this.options.map(option => {
				let clone = ObjectUtil.clone(option);
				// eslint-disable-next-line no-empty
				if (clone.editable === false) {
				} else {
					clone.editable = true;
				}
				if (clone.type === 'category') {
					console.assert(clone.options, '离散值的数据字典不存在');
					if (!clone.format) {
						clone.format = value =>
							clone.options.find(o => o.value === value).label;
					}
				} else if (clone.type === 'time') {
					console.assert(clone.format !== null, '时间的格式化');
				} else {
					clone.type = 'value';
				}
				return clone;
			});
		},
		inputOption: function() {
			return this.tableOptions.find(o => this.searchControl.choice === o.value);
		},
		defaultQuery: function() {
			const clone = ObjectUtil.clone(this.defaultRecord);
			Object.keys(clone).forEach(key => {
				const option = this.tableOptions.find(o => key === o.value);
				if (option?.type === 'time') {
					clone[key] = [null, null];
				} else {
					clone[key] = null;
				}
			});
			return clone;
		}
	},
	methods: {
		/************************* 回调 *************************/
		/******************** 搜索回调 ********************/
		choiceChange() {
			this.searchControl.query = ObjectUtil.clone(this.defaultQuery);
		},
		/******************** 表格回调 ********************/
		handleHeaderStyle() {
			return {
				'text-align': 'center',
				color: 'black',
				'font-size': '14px'
			};
		},
		sortChange(column) {
			if (column.prop) {
				this.tableControl.prop = column.prop;
			} else {
				this.tableControl.prop = null;
			}
			switch (column.order) {
				case 'ascending':
					this.tableControl.order = true;
					break;
				case 'descending':
					this.tableControl.order = false;
					break;
				default:
					this.tableControl.order = null;
					break;
			}
			this.select().catch(e => {
				this.$message.error(e.message);
			});
		},
		selectChange(selection) {
			this.tableControl.selection = selection;
		},
		/******************** 分页回调 ********************/
		pageSizeChange(size) {
			this.pageControl.pageSize = size;
			this.select().catch(e => {
				this.$message.error(e.message);
			});
		},
		currentChange(current) {
			this.pageControl.current = current;
			this.select().catch(e => {
				this.$message.error(e.message);
			});
		},
		/******************** 插入、更新回调 ********************/
		handleInsertCommand() {
			this.goPage(this.getPage(this.pageControl.total + 1)).then(() => {
				let row = ObjectUtil.clone(this.defaultRecord);
				row.editable = true;
				this.tableControl.tableData.push(row);
				this.setEditStatus(true, true, ObjectUtil.clone(this.defaultRecord));
			});
		},
		handleUpdateCommand(row) {
			row.editable = true;
			const record = ObjectUtil.omit(row, ['editable']);
			this.setEditStatus(true, false, record);
		},
		handleSaveSure(row) {
			if (ObjectUtil.equals(this.editControl.temp, row, ['editable'])) {
				if (this.editControl.isPlus) {
					// 没有填写信息
					this.$message.warning('未填写有效信息！');
					row.editable = false;
					this.tableControl.tableData.pop();
					this.setEditStatus(false, false, null);
					if (this.tableControl.tableData.length === 0) {
						this.pageControl.current -= 1;
						this.select().catch(e => {
							this.$message.error(e.message);
						});
					}
				} else {
					// 没有修改
					row.editable = false;
					this.setEditStatus(false, false, null);
					this.$message.success('未修改！');
				}
			} else {
				if (this.editControl.isPlus) {
					this.insertRecord(row);
				} else {
					this.updateRecord(row);
				}
			}
		},
		handleSaveClose(record) {
			if (this.editControl.isPlus) {
				this.tableControl.tableData.pop();
				this.setEditStatus(false, false, null);
				if (this.tableControl.tableData.length === 0) {
					this.pageControl.current -= 1;
					this.select().catch(e => {
						this.$message.error(e.message);
					});
				}
			} else {
				if (record.editable) {
					record.editable = false;
					record = { ...record, ...this.editControl.temp };
					this.setEditStatus(false, false, null);
				} else {
					let row = this.tableControl.tableData.find(
						value => value.id === record.id
					);
					Object.assign(row, record);
					row.editable = false;
					this.setEditStatus(false, false, null);
				}
			}
		},
		/******************** 删除、批量删除回调 ********************/
		handleDeleteCommand(row) {
			this.setDeleteStatus(true, false, row, null);
		},
		handleBatchDeleteCommand() {
			if (this.tableControl.selection) {
				this.setDeleteStatus(true, true, null, this.tableControl.selection);
			} else {
				this.$message.warning('没有选择项！');
			}
		},
		handleDeleteSure() {
			if (this.deleteControl.isBatch) {
				this.deleteRecords(this.deleteControl.deleteRows);
			} else {
				this.deleteRecord(this.deleteControl.deleteRow);
			}
		},
		handleDeleteCancel() {
			this.setDeleteStatus(false, false, null, null);
		},
		/************************* 副作用 *************************/
		goPage(current) {
			this.pageControl.current = current;
			return this.select().catch(e => {
				this.$message.error(e.message);
			});
		},
		select() {
			this.tableControl.loading = true;
			return this.service.selectLike(this.getQueryCondition()).then(resp => {
				this.tableControl.tableData = HttpUtil.getList(resp);
				this.tableControl.tableData.forEach(value => {
					this.$set(value, 'editable', false);
				});
				this.pageControl.total = HttpUtil.getPageInfo(resp).total;
				this.pageControl.pages = HttpUtil.getPageInfo(resp).pages;
				this.tableControl.loading = false;
				return resp;
			});
		},
		insertRecord(record) {
			this.tableControl.loading = true;
			this.service
				.insert(record)
				.then(resp => {
					if (HttpUtil.isCreated(resp)) {
						// 数据库插入成功
						record.editable = false;
						this.setEditStatus(false, false, null);
						this.$message.success('保存成功！');
					} else {
						// 数据库插入失败，服务器出错
						record.editable = false;
						this.setEditStatus(false, false, null);
						if (this.tableControl.tableData.length === 0) {
							this.pageControl.current -= 1;
						}
						this.$message.warning('保存失败！');
					}
				})
				.catch(e => {
					// 未知错误
					record.editable = false;
					this.setEditStatus(false, false, null);
					if (this.tableControl.tableData.length === 0) {
						this.pageControl.current -= 1;
					}
					this.$message.error(e.message);
				})
				.finally(() => this.select());
		},
		updateRecord(record) {
			this.tableControl.loading = true;
			this.service
				.update(record)
				.then(resp => {
					if (HttpUtil.isCreated(resp)) {
						// 数据库更新成功
						record.editable = false;
						this.setEditStatus(false, false, null);
						this.$message.success('保存成功！');
					} else {
						// 数据库更新失败，服务器出错
						record.editable = false;
						this.setEditStatus(false, false, null);
						this.$message.warning('保存失败！');
					}
				})
				.catch(e => {
					// 未知错误
					record.editable = false;
					this.setEditStatus(false, false, null);
					this.$message.error(e.message);
				})
				.finally(() => this.select());
		},
		deleteRecord(record) {
			this.tableControl.loading = true;
			this.service
				.deleteById(record.id)
				.then(resp => {
					if (HttpUtil.isNoContent(resp)) {
						// 数据库删除成功
						this.setDeleteStatus(false, false, null, null);
						if (this.tableControl.tableData.length === 1) {
							this.pageControl.current -= 1;
						}
						this.$message.success('删除成功！');
					} else {
						// 数据库删除失败
						this.setDeleteStatus(false, false, null, null);
						this.$message.error('删除失败！');
					}
				})
				.catch(e => {
					// 未知错误
					this.setDeleteStatus(false, false, null, null);
					this.$message.error(e.message);
				})
				.finally(() => this.select());
		},
		deleteRecords(records) {
			this.tableControl.loading = true;
			this.service
				.deleteByIds(records.map(record => record.id))
				.then(resp => {
					if (HttpUtil.isNoContent(resp)) {
						// 数据库删除成功
						this.setDeleteStatus(false, false, null, null);
						if (this.tableControl.tableData.length === records.length) {
							this.pageControl.current -= 1;
						}
						this.$message.success('删除成功!');
					} else {
						// 数据库删除失败
						this.setDeleteStatus(false, false, null, null);
						this.$message.error('删除失败!');
					}
				})
				.catch(e => {
					// 未知错误
					this.setDeleteStatus(false, false, null, null);
					this.$message.error(e.message);
				})
				.finally(() => this.select());
		},
		setEditStatus(editable, isPlus, temp) {
			this.editControl.editable = editable;
			this.editControl.isPlus = isPlus;
			this.editControl.temp = temp;
			this.$refs.table.doLayout();
		},
		setDeleteStatus(deletable, isBatch, deleteRow, deleteRows) {
			this.deleteControl.deletable = deletable;
			this.deleteControl.isBatch = isBatch;
			this.deleteControl.deleteRow = deleteRow;
			this.deleteControl.deleteRows = deleteRows;
		},
		/************************* 纯函数 *************************/
		getQueryCondition() {
			const queryCondition = {
				query: {},
				pageCondition: {
					pageNum: this.pageControl.current,
					pageSize: this.pageControl.pageSize
				},
				orderConditions: [
					{
						columns: [this.tableControl.prop],
						mode: this.tableControl.order
					}
				],
				columnCondition: {
					timeConditions: [],
					numberConditions: [],
					categoryConditions: []
				}
			};
			Object.keys(this.searchControl.query).forEach(key => {
				const option = this.tableOptions.find(o => key === o.value);
				if (option?.type === 'time') {
					queryCondition.query[key] = null;
					queryCondition.columnCondition.timeConditions.push({
						column: key,
						begin: this.searchControl.query[key][0],
						end: this.searchControl.query[key][1]
					});
				} else {
					queryCondition.query[key] = this.searchControl.query[key];
				}
			});
			return queryCondition;
		},
		getPage(index) {
			return Math.ceil(index / this.pageControl.pageSize);
		}
	}
};
